home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / whitelin / share / boxkite / beispiel.c next >
C/C++ Source or Header  |  1995-11-25  |  10KB  |  397 lines

  1. /*
  2.  * Beispiel-Programm zur Benutzung des Selectric-Protokolls mit BoxKite
  3.  * unter MiNT/MultiTOS/MagiC/MagiC Mac
  4.  * (c) Harald Becker, 12.5.1994. Übersetzt mit Pure C und DEFAULT.PRJ.
  5.  *
  6.  * Diesen Code dürfen Sie nach Belieben verwenden und ganz oder in in Auszügen
  7.  * in Ihre Programme aufnehmen.
  8.  *
  9.  * HB 061095:
  10.  * Erweitert um eine Anwendung für den Message-Callback in BoxKite 1.7x
  11.  * Dazu wird hinter dem Fileselector ein kleines Fenster geöffnet,
  12.  * das über den Message-Callback gezeichnet wird. Es kann auch
  13.  * verschoben werden, falls das Betriebssystem das Verschieben hinten-
  14.  * liegender Fenster erlaubt.
  15.  *
  16.  * HB 131095:
  17.  * Inzwischen demonstriert das Programm alle drei möglichen Rückgabeformen.
  18.  * Die Auswahl erfolgt zur Compile-Zeit über die Konstante 'RETURN'.
  19.  */
  20. #include <stdio.h>
  21. #include <aes.h>
  22. #include <tos.h>
  23. #include <string.h>
  24.  
  25. /*
  26.  * Diese Konstante steuert, welche Rückgabemethode das Beispielprogramm
  27.  * bei BoxKite anfordert. Mögliche Werte:
  28.  *
  29.  *     1: Rückgabe über ein Feld von Stringzeigern
  30.  *     2: Rückgabe über einen String (mit trennenden Leerzeichen)
  31.  *     3: Rückgabe über Funktionen
  32.  */
  33. #define RETURN 1
  34.  
  35. /*
  36.  * Diese Struktur wird von BoxKite gefüllt. Sie ist identisch mit der
  37.  * TOS-DTA, sieht jedoch Platz für lange Datenamen vor.
  38.  */
  39. typedef struct
  40. {    char            d_reserved[21];
  41.     unsigned char    d_attrib;
  42.     unsigned int    d_time;
  43.     unsigned int    d_date;
  44.     unsigned long    d_length;
  45.     char            d_fname[34];
  46. } XDTA;
  47.  
  48. /*
  49.  * Die Selectric-Struktur.
  50.  */
  51. typedef struct
  52. {    unsigned long    id;            /* Selectric ID (SLCT)        */
  53.     unsigned int    version;    /* version (BCD-Format)        */
  54.     struct
  55.     {    unsigned           : 7;    /* reserved                     */
  56.         unsigned pthsav    : 1;
  57.         unsigned stdest    : 1;
  58.         unsigned           : 1;
  59.         unsigned numsrt    : 1;   /* numerisches Sortieren     */
  60.         unsigned lower     : 1;
  61.         unsigned dclick    : 1;   /* Ordner mit Doppelklick    */
  62.         unsigned hidden    : 1;   /* versteckte Dateien        */
  63.         unsigned onoff     : 1;   /* Fileselector AN/AUS       */
  64.     } config;
  65.     int    sort;            /* sort-mode (neg. = rev.)    */
  66.     int    num_ext;        /* number of extensions        */
  67.     char *(*ext)[];        /* preset extensions        */
  68.     int    num_paths;        /* number of paths        */
  69.     char *(*paths)[];        /* preset paths            */
  70.     int    comm;            /* communication word        */
  71.     int    in_count;        /* input counter        */
  72.     void *in_ptr;        /* input pointer        */
  73.     int    out_count;        /* output counter        */
  74.     void *out_ptr;        /* output pointer        */
  75.     int    cdecl    (*get_first)(XDTA *dta, int attrib);
  76.     int    cdecl     (*get_next)(XDTA *dta);
  77.     int    cdecl    (*release_dir)(void);
  78. } SLCT_STR;
  79.  
  80. typedef struct
  81. {    long    id;
  82.     long    value;
  83. } COOKIE;
  84.  
  85. long Supexec(long (*codeptr)());
  86.  
  87. SLCT_STR *slct_cookie;
  88.  
  89. /*
  90.  * Prototyp des Message-Handlers.
  91.  */
  92. typedef void cdecl (* FSEL_CALLBACK)(int *msg);
  93.  
  94. /*
  95.  * Prototyp des erweiterten Bindings.
  96.  */
  97. int cdecl fsel_boxinput(char *path, char *name, int *button, char *label, FSEL_CALLBACK callback);
  98.  
  99. /*
  100.  * Variablen für die Rückgabe der Dateinamen.
  101.  */
  102. #if RETURN == 1
  103.     char name1[34], name2[34], name3[34];
  104.     char *nameptrs[] = { name1, name2, name3 };
  105. #elif RETURN == 2
  106.     char stringbuf[256];
  107. #else
  108.     int    cdecl (*p_get_first)(XDTA *dta, int attrib);
  109.     int    cdecl (*p_get_next)(XDTA *dta);
  110.     int    cdecl (*p_release_dir)(void);
  111. #endif
  112.  
  113. int name_count;        /* Anzahl der gelieferten Namen */
  114.  
  115. int window;            /* Fensterkennung */
  116. OBJECT contents =     /* Fensterinhalt */
  117.     { -1, -1, -1, G_BOXCHAR, 0, 0, 0x2aff11f0, 1, 1, 1, 1 };
  118.  
  119. int xdesk, ydesk, wdesk, hdesk;
  120.  
  121. /*
  122.  * Gibt die Adresse des Cookie-Jar zurück. Mit Supexec() aufrufen.
  123.  */
  124. long get_cookiejar(void)
  125. {    return *((long *)0x05a0l);
  126. }
  127.  
  128. /*
  129.  * Durchsucht den Cookie Jar nach einem cookie mit gegebener id und
  130.  * liefert dessen Wert zurück.
  131.  */
  132. long get_cookie(long id)
  133. {    long sav;
  134.     COOKIE *cookiejar;
  135.     int    i = 0;
  136.  
  137.     cookiejar = (COOKIE *)Supexec(get_cookiejar);
  138.  
  139.     if ( cookiejar )
  140.     {    while ( cookiejar[i].id )
  141.         {    if ( cookiejar[i].id == id )
  142.                 return cookiejar[i].value;
  143.             i++;
  144.         }
  145.     }
  146.     return 0L;
  147. }
  148.  
  149. /*
  150.  * Prüft, ob am 'FSEL'-cookie ein Selectric-1.02-kompatibler Fileselector
  151.  * hängt. Im Erfolgsfall wird die Datenstruktur hinter dem Cookie für die
  152.  * gewünschte Rückgabeform initialisiert.
  153.  * Sollte mit Supexec aufgerufen werden, da der Speicher immerhin einem
  154.  * fremden Prozeß gehört.
  155.  */
  156. long setup_selector(void)
  157. {    if ( slct_cookie && slct_cookie->id == 'SLCT' && slct_cookie->version >= 0x102 )
  158.     {
  159. #if RETURN == 1    
  160.         slct_cookie->comm = 1;
  161.         slct_cookie->out_count = 3;
  162.         slct_cookie->out_ptr = nameptrs;
  163. #elif RETURN == 2
  164.         slct_cookie->comm = 3;
  165.         slct_cookie->out_count = 5;
  166.         slct_cookie->out_ptr = stringbuf;
  167. #else
  168.         slct_cookie->comm = 9;
  169.         p_get_first = slct_cookie->get_first;
  170.         p_get_next = slct_cookie->get_next;
  171.         p_release_dir = slct_cookie->release_dir;
  172.  
  173. #endif
  174.         return 1;
  175.     }
  176.     return 0;
  177. }
  178.  
  179. /*
  180.  * Liest die Anzahl der gelieferten Namen aus der FSEL-Struktur.
  181.  */
  182. long get_out_count(void)
  183. {    name_count = slct_cookie->out_count;
  184.     return 0;
  185. }
  186.  
  187. /*
  188.  * Fragt das aktuelle Laufwerk und den aktuellen Pfad ab.
  189.  */
  190. void getpath(char *p)
  191. {    int drv;
  192.  
  193.     drv = Dgetdrv();
  194.     *p++ = drv + 'A';
  195.     *p++ = ':';
  196.     Dgetpath(p, drv);
  197.     p += strlen(p) - 1;
  198.     if ( *p != '\\' )
  199.     {    p++;
  200.         *p++ = '\\';
  201.         *p = 0;
  202.     }
  203. }
  204.  
  205. /* 
  206.  * Die folgenden vier Funktionen befassen sich nur mit dem Zeichnen
  207.  * des Fensterinhaltes. Ich denke, die Methode hat sich inzwischen
  208.  * herumgesprochen.
  209.  */
  210. int min(int a, int b)
  211. {    return ( a < b ? a : b );
  212. }
  213.  
  214. int max(int a, int b)
  215. {    return ( a > b ? a : b );
  216. }
  217.  
  218. int rc_intersect(GRECT *p1, GRECT *p2)
  219. {    int tx, ty, tw, th;
  220.  
  221.     tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
  222.     th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
  223.     tx = max(p2->g_x, p1->g_x);
  224.     ty = max(p2->g_y, p1->g_y);
  225.  
  226.     p2->g_x = tx;
  227.     p2->g_y = ty;
  228.     p2->g_w = tw - tx;
  229.     p2->g_h = th - ty;
  230.  
  231.     return( (tw > tx) && (th > ty) );
  232. }
  233.  
  234. void window_redraw(int handle, int x, int y, int w, int h)
  235. {    GRECT r1, r2, world;
  236.  
  237.     wind_update(BEG_UPDATE);
  238.  
  239.     r2.g_x = x;
  240.     r2.g_y = y;
  241.     r2.g_w = w;
  242.     r2.g_h = h;
  243.  
  244.     world.g_x = xdesk;
  245.     world.g_y = ydesk;
  246.     world.g_w = wdesk;
  247.     world.g_h = hdesk;
  248.  
  249.     wind_get(handle, WF_FIRSTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
  250.     while ( r1.g_w && r1.g_h )
  251.     {    if ( rc_intersect(&world, &r1) && rc_intersect(&r2, &r1) )
  252.             objc_draw(&contents, ROOT, MAX_DEPTH, r1.g_x, r1.g_y, r1.g_w, r1.g_h);
  253.         wind_get(handle, WF_NEXTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
  254.     }
  255.     wind_update(END_UPDATE);
  256. }
  257.  
  258. /* 
  259.  * Die Einsprungadresse dieser Funktion wird als Callback an BoxKite
  260.  * übergeben.
  261.  */
  262. void cdecl message_handler(int *msg)
  263. {    switch ( msg[0] )
  264.     {    case WM_REDRAW:
  265.             wind_get(msg[3], WF_WORKXYWH, &contents.ob_x, &contents.ob_y, &contents.ob_width, &contents.ob_height);
  266.             window_redraw(msg[3], msg[4], msg[5], msg[6], msg[7]);
  267.             break;
  268.         case WM_MOVED:
  269.             wind_set(msg[3], WF_CURRXYWH, msg[4], msg[5], msg[6], msg[7]);
  270.             break;
  271.     }
  272. }
  273.  
  274. /*
  275.  * Ein alternatives Binding für fsel_exinput() (Die Funktionsnummer ist
  276.  * identisch!), das die Übergabe der Callback-Adresse erlaubt. Andere
  277.  * Fileselectoren sollten den überzähligen Parameter einfach ignorieren.
  278.  *
  279.  * Eine Assembler-Version dieses Bindings, die keine Annahmen über das
  280.  * Vorhandensein eines generellen GEM-Traps (hier: '_crystal') im
  281.  * verwendeten Entwicklungssystem macht, befindet sich im Quelltext in
  282.  * 'BOXINPUT.S' und als Objektdatei im DRI-Format in 'BOXINPUT.O'.
  283.  */
  284. int cdecl fsel_boxinput(char *path, char *name, int *button, char *label, FSEL_CALLBACK callback)
  285. {    void *aespb[6], *addrin[6], *addrout[6];
  286.     int contrl[5], global[15], intin[16], intout[7];
  287.  
  288.     aespb[0] = contrl;
  289.     aespb[1] = global;
  290.     aespb[2] = intin;
  291.     aespb[3] = intout;
  292.     aespb[4] = addrin;
  293.     aespb[5] = addrout;
  294.  
  295.     contrl[0] = 91;
  296.     contrl[1] = 0;
  297.     contrl[2] = 2;
  298.     contrl[3] = 4;
  299.     contrl[4] = 0;
  300.  
  301.     addrin[0] = path;
  302.     addrin[1] = name;
  303.     addrin[2] = label;
  304.     addrin[3] = callback;
  305.  
  306.     _crystal((AESPB *)aespb);
  307.  
  308.     *button = intout[1];
  309.     return intout[0];
  310. }
  311.  
  312. int main(void)
  313. {    XDTA mydta;
  314.     char path[130], name[34], outbuf[300];
  315.     int exbtn, rv, d, i;
  316.  
  317.     appl_init();
  318.     wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
  319.  
  320.     slct_cookie = (SLCT_STR *)get_cookie('FSEL');
  321.  
  322.     if ( !Supexec(setup_selector) )
  323.     {    form_alert(1, "[1][Kein kompatibler Fileselector|installiert.][   Ok   ]");
  324.         appl_exit();
  325.         return 0;
  326.     }
  327.  
  328.     Pdomain(1);            /* Damit auch wirklich lange Namen rauskommen */
  329.  
  330.     /*
  331.      * Ein Fenster hinter dem Fileselector öffenen, damit man sieht,
  332.      * daß auch etwas beim Message-Callback ankommt.
  333.      */
  334.     window = wind_create(NAME | MOVER, xdesk, ydesk, wdesk, hdesk);
  335.     if ( window < 0 )
  336.     {    form_alert(1, "[1][Das Fenster klemmt mal wieder!][   Ok   ]");
  337.         appl_exit();
  338.         return 0;
  339.     }
  340.     wind_set(window, WF_NAME, "Noch'n Fenster");
  341.     wind_open(window, xdesk + 50, ydesk + 50, 300, 200);
  342.     window_redraw(window, xdesk, ydesk, wdesk, hdesk);
  343.  
  344.     getpath(path);
  345.     strcat(path, "*.*");
  346.     *name = 0;
  347. #if RETURN == 1
  348.     do
  349.     {    Supexec(setup_selector);
  350.         rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
  351.  
  352.         if ( rv && exbtn )
  353.         {    Supexec(get_out_count);
  354.             for ( i = 0; i < name_count; i++ )
  355.             {    sprintf(outbuf, "[1][Datei Nr: %d|%s][   Ok   ]", i + 1, nameptrs[i]);
  356.                 form_alert(1, outbuf);
  357.             }
  358.         }
  359.     }
  360.     while ( rv && exbtn );    
  361. #elif RETURN == 2
  362.     do
  363.     {    Supexec(setup_selector);
  364.         rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
  365.  
  366.         if ( rv && exbtn )
  367.         {    sprintf(outbuf, "[1][%s][   Ok   ]", stringbuf);
  368.             form_alert(1, outbuf);
  369.         }
  370.     }
  371.     while ( rv && exbtn );
  372. #else
  373.     do
  374.     {    Supexec(setup_selector);
  375.         rv = fsel_boxinput(path, name, &exbtn, "BoxKite", &message_handler);
  376.         if ( rv && exbtn )
  377.         {    wind_update(BEG_UPDATE);
  378.             d = p_get_first(&mydta, 0xff);
  379.             i = 1;
  380.             while( !d )
  381.             {    sprintf(outbuf, "[1][Datei Nr %d:|%s %02x][   Ok   ]", i, mydta.d_fname, mydta.d_attrib);
  382.                 form_alert(1, outbuf);
  383.                 d = p_get_next(&mydta);
  384.                 i++;
  385.             }
  386.             p_release_dir();
  387.             wind_update(END_UPDATE);
  388.         }
  389.     }
  390.     while ( rv && exbtn );
  391. #endif
  392.     wind_close(window);
  393.     wind_delete(window);
  394.     appl_exit();
  395.     return 0;
  396. }
  397.